package com.navinfo.platform.trip.common.arithmetic;

import com.navinfo.platform.trip.common.arithmetic.annotation.Arithmetic;
import com.navinfo.platform.trip.common.arithmetic.data.CommonData;
import com.navinfo.platform.trip.common.arithmetic.data.OuterStatisticData;
import com.navinfo.platform.trip.common.arithmetic.enums.EventStatus;
import com.navinfo.platform.trip.common.arithmetic.enums.EventType;
import com.navinfo.platform.trip.common.arithmetic.manager.AbstractArithmetic;
import com.navinfo.platform.trip.common.arithmetic.var.VarCommonNumber;
import com.navinfo.platform.trip.common.arithmetic.var.VarGasLargeAndFull;
import com.navinfo.platform.trip.common.config.ConfigMap;
import com.navinfo.platform.trip.common.util.ArithmeticUtils;

import java.util.Optional;

/**
 * 东风大油门和全油门算法<br/>
 * 依赖{@link Mileage}里程油耗算法<br/>
 * 输出：统计、事件<br/>
 * @author web
 */
@Arithmetic(name = "东风大油门和全油门算法")
public class GasLargeAndFull_DF extends AbstractArithmetic<VarGasLargeAndFull> {
    /**
     * 大油门事件
     */
    private EventType largeGasEvent = EventType.largeAccelerator_DF;
    /**
     * 全油门事件
     */
    private EventType fullGasEvent = EventType.fullAccelerator_DF;
    /**
     * 东风大油门阀值
     */
    private static final int LARGE_GAS_THRESHOLD = ConfigMap.getInteger("DF_Large_Gas_Threshold");
    /**
     * 东风全油门阀值
     */
    private static final int FULL_GAS_THRESHOLD = ConfigMap.getInteger("DF_Full_Gas_Threshold");

    /**
     * 大油门判断
     */
    private boolean isLargeGas(){
        CommonData commonData = getCommonData();
        return commonData.getRotation()>0 && commonData.getAcceleratorPosition()>=LARGE_GAS_THRESHOLD && commonData.getAcceleratorPosition()<FULL_GAS_THRESHOLD;
    }

    /**
     * 全油门判断
     */
    private boolean isFullGas(){
        CommonData commonData = getCommonData();
        return commonData.getRotation()>0 && commonData.getAcceleratorPosition()>FULL_GAS_THRESHOLD;
    }

    @Override
    public void calculate() {
        calcLargeGas();
        calcFullGas();
    }

    @Override
    public void collect(OuterStatisticData statisticDataOut) {
        VarGasLargeAndFull var = getObj();
        VarCommonNumber largeGas = var.getLargeGas();
        statisticDataOut.setLargeGasMileage_DF(ArithmeticUtils.mileageMToM(largeGas.getMileage()));
        statisticDataOut.setLargeGasFuel_DF(ArithmeticUtils.fuelMlToMl(largeGas.getFuel()));
        statisticDataOut.setLargeGasDuration_DF(ArithmeticUtils.timeMsToSecond(largeGas.getDuration()));
        statisticDataOut.setLargeGasNumber_DF(largeGas.getNumber());

        VarCommonNumber fullGas = var.getFullGas();
        statisticDataOut.setFullGasMileage_DF(ArithmeticUtils.mileageMToM(fullGas.getMileage()));
        statisticDataOut.setFullGasFuel_DF(ArithmeticUtils.fuelMlToMl(fullGas.getFuel()));
        statisticDataOut.setFullGasDuration_DF(ArithmeticUtils.timeMsToSecond(fullGas.getDuration()));
        statisticDataOut.setFullGasNumber_DF(fullGas.getNumber());
    }

    /**
     * 计算大油门
     */
    private void calcLargeGas() {
        logger.debug("===============东风大油门算法开始===========");
        VarGasLargeAndFull var = getObj();
        boolean preState= var.isPreLargeGas();
        boolean curState = isLargeGas();
        logger.debug("进入东风大油门算法，前一点状态：{}，当前点状态：{}，[terminalId:{}]", preState, curState, terminalId);

        EventStatus eventStatus = getEventStatus(preState, curState);
        switch (eventStatus) {
            case START:
                logger.debug("东风大油门算法，事件开始.[terminalId:{}]", terminalId);
                startEventData(largeGasEvent);
                break;
            case IN:
                logger.debug("东风大油门算法，事件中.[terminalId:{}]", terminalId);
                calcEventData(largeGasEvent);
                break;
            case END:
                logger.debug("东风大油门算法，事件结束.[terminalId:{}]", terminalId);
                calcEventData(largeGasEvent);
                endLargeGasEvent(var);
                break;
            default:
                logger.debug("跳出东风大油门算法.[terminalId:{}]", terminalId);
        }

        //行程结束时要清理对应的未结束事件
        if (getCommonData().isTripLastNode()) {
            endLargeGasEvent(var);
        }

        //更新状态，供下个点使用
        var.setPreLargeGas(curState);
        logger.debug("===============东风大油门算法结束===========");
    }

    /**
     * 计算全油门
     */
    private void calcFullGas() {
        logger.debug("===============东风全油门算法开始===========");
        VarGasLargeAndFull var = getObj();
        boolean preState= var.isPreFullGas();
        boolean curState = isFullGas();
        logger.debug("进入东风全油门算法，前一点状态：{}，当前点状态：{}，[terminalId:{}]", preState, curState, terminalId);

        EventStatus eventStatus = getEventStatus(preState, curState);
        switch (eventStatus) {
            case START:
                logger.debug("东风全油门算法，事件开始.[terminalId:{}]", terminalId);
                startEventData(fullGasEvent);
                break;
            case IN:
                logger.debug("东风全油门算法，事件中.[terminalId:{}]", terminalId);
                calcEventData(fullGasEvent);
                break;
            case END:
                logger.debug("东风全油门算法，事件结束.[terminalId:{}]", terminalId);
                calcEventData(fullGasEvent);
                endFullGasEvent(var);
                break;
            default:
                logger.debug("跳出东风全油门算法.[terminalId:{}]", terminalId);
        }

        //行程结束时要清理对应的未结束事件
        if (getCommonData().isTripLastNode()) {
            endFullGasEvent(var);
        }

        //更新状态，供下个点使用
        var.setPreFullGas(curState);
        logger.debug("===============东风全油门算法结束===========");
    }

    private void endLargeGasEvent(VarGasLargeAndFull var){
        endEventData(largeGasEvent, eventData -> {
            VarCommonNumber largeGas = var.getLargeGas();
            largeGas.addNumber(1);
            largeGas.addMileage( Optional.ofNullable(eventData.getExtendField05()).orElse(0.0));
            largeGas.addFuel(Optional.ofNullable(eventData.getExtendField06()).orElse(0.0));
            largeGas.addDuration(Optional.ofNullable(eventData.getDuration()).orElse(0L).intValue());
        });
    }

    private void endFullGasEvent(VarGasLargeAndFull var){
        endEventData(fullGasEvent, eventData -> {
            VarCommonNumber fullGas = var.getFullGas();
            fullGas.addNumber(1);
            fullGas.addMileage( Optional.ofNullable(eventData.getExtendField05()).orElse(0.0));
            fullGas.addFuel(Optional.ofNullable(eventData.getExtendField06()).orElse(0.0));
            fullGas.addDuration(Optional.ofNullable(eventData.getDuration()).orElse(0L).intValue());
        });
    }

}
